#include <assert.h>
#include <DXGI.h>
#include "../Base/Log.h"
#include "../Game/WinApp.h"
#include "RenderEngine.h"

namespace cy_univerX
{

namespace render
{
	 CRenderEngine& CRenderEngine::Instance()
	 {
		 static CRenderEngine g_render_engine;
		 return g_render_engine;
	 }

	CRenderEngine::CRenderEngine()
	{
		HRESULT hr = S_OK;

		D3D_DRIVER_TYPE driver_type = D3D_DRIVER_TYPE_HARDWARE; //D3D_DRIVER_TYPE_WARP/D3D_DRIVER_TYPE_REFERENCE/D3D_DRIVER_TYPE_SOFTWARE

		UINT create_device_flags = 0;

		D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
		D3D_FEATURE_LEVEL out_feature_level;

		hr = D3D11CreateDevice(
			NULL, driver_type, NULL, create_device_flags,
			&featureLevel, 1, D3D11_SDK_VERSION,
			&m_Device, &out_feature_level, &m_ImmediateDeviceContext);

		if( FAILED( hr ) )
		{
			log::CLogger::Instance().Output(log::LL_Error, "D3D11CreateDevice error");
			assert(false);
		}

		IDXGIDevice *dxgi_device;
		hr = m_Device->QueryInterface(IID_IDXGIDevice, (void **)&dxgi_device);
		if( FAILED( hr ) )
		{
			log::CLogger::Instance().Output(log::LL_Error, "Get GI Device error");
			assert(false);
		}
      
		IDXGIAdapter *dxgi_adapter;
		hr = dxgi_device->GetParent(IID_IDXGIAdapter, (void **)&dxgi_adapter);
		if( FAILED( hr ) )
		{
			log::CLogger::Instance().Output(log::LL_Error, "Get GI Adapter error");
			assert(false);
		}

		//IDXGIFactory1  * dxgi_factory;
		hr = dxgi_adapter->GetParent(IID_IDXGIFactory1, (void **)&m_DxGiFactory);
		if( FAILED( hr ) )
		{
			log::CLogger::Instance().Output(log::LL_Error, "Get GI Factory error");
			assert(false);
		}

		InitCache();
	}

	CRenderEngine::~CRenderEngine()
	{
		m_ImmediateDeviceContext->ClearState();
		m_Device->Release();
	}

	void CRenderEngine::InitCache()
	{
		m_BsCache = 0;
		m_BlendFactorCache.Set(1,1,1,1);
		m_SampleMaskCache = 0xffffffff;

		m_RsCache = 0;

		m_DssCache = 0;
		m_StencilRefCache = 0;

		m_VsCache = 0;
		m_PsCache = 0;
		m_GsCache = 0;
		m_CsCache = 0;
		m_HsCache = 0;
		m_DsCache = 0;

		m_InputLayoutCache = 0;

		m_PrimitiveTopologyCache = D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED;

		memset(m_SamplerStateCache, 0, sizeof(m_SamplerStateCache) );
		memset(m_SrvCache, 0, sizeof(m_SrvCache) );
		memset(m_CBufferCache, 0, sizeof(m_CBufferCache) );
	}

	/*
    // Create a render target view
    ID3D11Texture2D* pBackBuffer = NULL;
    hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
    if( FAILED( hr ) )
        return hr;

    hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
    pBackBuffer->Release();
    if( FAILED( hr ) )
        return hr;

    g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );

    // Setup the viewport
    D3D11_VIEWPORT vp;
    vp.Width = (FLOAT)width;
    vp.Height = (FLOAT)height;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pImmediateContext->RSSetViewports( 1, &vp );

    return S_OK;
	}
	*/
}
}